package com.jp.fm.servlet;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jp.fm.HomeFinanceRunner;
import com.jp.fm.data.BillReminder;
import com.jp.fm.data.Budget;
import com.jp.fm.data.Category;

public class ShowAccountSummary extends ServletParent {

	private static final int TOP_CATEGORY_TIME_FRAME_MONTHS = -6;
	private static final int MIN_DAYS_TO_LOOK_FOR_UPCOMING_BILLS = 7;
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Constructor of the object.
	 */
	public ShowAccountSummary() {
		super();
	}

	/**
	 * Destruction of the servlet. <br>
	 */
	public final void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	public final void doGet(final HttpServletRequest request,
			final HttpServletResponse response) throws ServletException,
			IOException {

		doPost(request, response);
	}

	public final void doPost(final HttpServletRequest request,
			final HttpServletResponse response) throws ServletException,
			IOException {

		List<String> alerts = new ArrayList<String>();

		// Get data for the left nav bar
		getPageService().composeRequestLeftNav(request);

		request.setAttribute("allAccounts", getAccountDao().findAll());
		request.setAttribute("allCategories", getCategoryDao().findAll());

		// Lookup upcoming bills and them to the response.
		composeBills(request);

		// Lookup budget items and them to the response.
		composeBudgets(request, alerts);

		// Get top categories
		composeTopCategories(request);

		// Lookup alerts and them to the response.
		composeAlerts(request, alerts);

		RequestDispatcher rd = request
				.getRequestDispatcher("/secured/AccountSummary.jsp");
		rd.forward(request, response);
	}

	protected void composeAlerts(final HttpServletRequest request,
			final List<String> alerts) {
		alerts.addAll(getTransactionService().findUncategorizedTransactions());
		alerts.addAll(getTransactionService().findFeeTransactions());
		alerts.addAll(getPageService().findAccountAlerts());
		alerts.addAll(getPageService().findCreditAlerts());
		alerts.addAll(getTransactionService().findUnconfirmedTransactions());
		request.setAttribute("alerts", alerts);
	}

	protected void composeBills(final HttpServletRequest request) {
		List<String> bills = new ArrayList<String>();
		List<BillReminder> billReminders = getBillReminderDao()
				.findByDueDateAndRange(MIN_DAYS_TO_LOOK_FOR_UPCOMING_BILLS);

		for (Iterator<BillReminder> iterator = billReminders.iterator(); iterator
				.hasNext();) {
			BillReminder billReminder = iterator.next();

			String reminderStr = billReminder.getName()
					+ " is due in "
					+ HomeFinanceRunner.getLastUpdateText(new Timestamp(
							billReminder.getDueDate().getTime()));

			bills.add(reminderStr);
		}
		request.setAttribute("bills", bills);

		List<BillReminder> allBills = getBillReminderDao().findAll();
		request.setAttribute("allBills", allBills);
	}

	protected void composeTopCategories(final HttpServletRequest request) {

		Calendar now = new GregorianCalendar();
		Calendar startMonth = new GregorianCalendar();
		startMonth.set(Calendar.DAY_OF_MONTH, 1);
		Map<Float, Category> topCatMap = getCategoryService()
				.getTopCategoriesOverTimeFrame(startMonth.getTime(),
						now.getTime());

		Calendar calMinusSixMonths = new GregorianCalendar();
		calMinusSixMonths.add(Calendar.MONTH, TOP_CATEGORY_TIME_FRAME_MONTHS);
		calMinusSixMonths.set(Calendar.DAY_OF_MONTH, 1);
		Map<Float, Category> topCatMapSixMonths = getCategoryService()
				.getTopCategoriesOverTimeFrame(calMinusSixMonths.getTime(),
						now.getTime());

		// remove the Deposit and Mortgage categories because they do not
		// need to be displayed
		Map<Float, Category> topCatMapFinal = new TreeMap<Float, Category>(
				new HomeFinanceRunner.ReverseFloatComparator());
		Map<Float, Category> topCatMapSixMonthsFinal = new TreeMap<Float, Category>(
				new HomeFinanceRunner.ReverseFloatComparator());

		Set<Entry<Float, Category>> entries = topCatMap.entrySet();
		for (Entry<Float, Category> entry : entries) {

			if (!"Deposit".equals(entry.getValue().getName())
					&& !"Mortgage".equals(entry.getValue().getName())) {

				topCatMapFinal.put(entry.getKey(), entry.getValue());
			}
		}
		request.setAttribute("topCategoriesThisMonth", topCatMapFinal);

		entries = topCatMapSixMonths.entrySet();
		for (Entry<Float, Category> entry : entries) {

			if (!"Deposit".equals(entry.getValue().getName())
					&& !"Mortgage".equals(entry.getValue().getName())) {

				topCatMapSixMonthsFinal.put(entry.getKey(), entry.getValue());
			}
		}
		request.setAttribute("topCategories", topCatMapSixMonthsFinal);
	}

	protected void composeBudgets(final HttpServletRequest request,
			final List<String> alerts) {
		Calendar now = new GregorianCalendar();
		Calendar startMonth = new GregorianCalendar();
		startMonth.set(Calendar.DAY_OF_MONTH, 1);

		List<Budget> budgetList = getBudgetService().findBudgetList(
				startMonth.getTime(), now.getTime(), alerts);

		// If no budgets found then try rolling over from last month
		if (null != budgetList && budgetList.size() == 0) {
			getBudgetDao().copyBudgetsFromLastMonth();
			budgetList = getBudgetService().findBudgetList(
					startMonth.getTime(), now.getTime(), alerts);
		}

		request.setAttribute("budgetList", budgetList);
	}
}
